package com.demo.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.sql.DataSource;

import net.sf.log4jdbc.Log4jdbcProxyDataSource;
import net.sf.log4jdbc.tools.Log4JdbcCustomFormatter;
import net.sf.log4jdbc.tools.LoggingType;

import org.apache.ibatis.builder.BuilderException;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import com.alibaba.druid.pool.DruidDataSource;

public class BaseConfig {

	/**
	 * 获得 SqlSessionFactory
	 * 
	 * @param config
	 * @return
	 */
	public SqlSessionFactory getSqlSessionFactory(String config) {
		try (InputStream is = Resources.getResourceAsStream(config)) {
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
			Configuration configuration = sqlSessionFactory.getConfiguration();

			DataSource ds = log4jdbcProxyDataSource(configuration.getEnvironment().getDataSource());

			configuration.setEnvironment(new Environment("development", new JdbcTransactionFactory(), ds));
			return sqlSessionFactory;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 获得 SqlSessionFactory
	 * 
	 * @param config
	 * @return
	 */
	public SqlSessionFactory getSqlSessionFactory(DataSource dataSource) {
		Environment environment = new Environment("development", new JdbcTransactionFactory(), dataSource);
		Configuration configuration = new Configuration(environment);
		return new SqlSessionFactoryBuilder().build(configuration);
	}

	/**
	 * 添加 mapping
	 * 
	 * @param configuration
	 * @param resource (resource or url)
	 * @throws Exception
	 */
	public void addMapping(Configuration configuration, String resource) {
		try {
			if (resource != null) {
				ErrorContext.instance().resource(resource);
				InputStream inputStream = null;
				if (resource.toLowerCase().startsWith("file:")) {
					inputStream = Resources.getUrlAsStream(resource);
				} else {
					inputStream = Resources.getResourceAsStream(resource);
				}
				XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource,
						configuration.getSqlFragments());
				mapperParser.parse();
			} else {
				throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/*--------------------------------------------------------------------------------*/
	static final String jdbcFilePath = Class.class.getResource("/jdbc.properties").getFile();

	protected boolean log4jdbcProxyDataSource() {
		return true;
	}

	public DataSource log4jdbcProxyDataSource(DataSource ds) {
		if (log4jdbcProxyDataSource()) {
			Log4JdbcCustomFormatter format = new Log4JdbcCustomFormatter();
			format.setLoggingType(LoggingType.MULTI_LINE);
			format.setSqlPrefix("SQL:::");
			Log4jdbcProxyDataSource proxy = new Log4jdbcProxyDataSource(ds);
			proxy.setLogFormatter(format);
			ds = proxy;
		}
		return ds;
	}

	public DataSource getDataSource() {
		try {
			Properties jdbcProp = new Properties();
			jdbcProp.load(new FileInputStream(jdbcFilePath));
			DruidDataSource ds = new DruidDataSource();
			ds.setDriverClassName(jdbcProp.getProperty("driverClassName"));
			ds.setUrl(jdbcProp.getProperty("jdbcUrl"));
			ds.setUsername(jdbcProp.getProperty("user"));
			ds.setPassword(jdbcProp.getProperty("password"));

			return log4jdbcProxyDataSource(ds);
		} catch (FileNotFoundException e) {
			throw new RuntimeException("文件没找到：", e);
		} catch (IOException e) {
			throw new RuntimeException("文件读取错误：", e);
		}
	}
}
